{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load text with tf.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras import layers\n",
    "\n",
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 搭建序贯模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = tf.keras.Sequential([\n",
    "    # 添加一个有 64 个神经元的全连接层，“input_shape”为该层接受的输入数据的维度\n",
    "    # “activation”指定该层所用的激活函数\n",
    "    layers.Dense(64, activation='relu', input_shape=(32,)),\n",
    "    # 添加第二个网络层\n",
    "    layers.Dense(64, activation='relu'),\n",
    "    # 添加一个 softmax 层作为输出层，该层有十个单元\n",
    "    layers.Dense(10, activation='softmax'),\n",
    "    ])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = tf.keras.Sequential()\n",
    "model.add(layers.Dense(64, activation='relu', input_shape=(32,)))\n",
    "model.add(layers.Dense(64, activation='relu'))\n",
    "model.add(layers.Dense(10, activation='softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 编译模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.compile(optimizer=tf.keras.optimizers.Adam(0.001),\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用numpy数据训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "data = np.random.random((1000, 32))\n",
    "labels = np.random.random((1000, 10))\n",
    "print(data[0])\n",
    "print(labels[0])\n",
    "model.fit(data, labels, epochs=2, batch_size=50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用验证集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "val_data = np.random.random((100, 32))\n",
    "val_labels = np.random.random((100, 10))\n",
    "\n",
    "model.fit(data, labels, epochs=2, batch_size=50,\n",
    "          validation_data=(val_data, val_labels))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  使用tf.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建训练集Dataset\n",
    "dataset = tf.data.Dataset.from_tensor_slices((data, labels))\n",
    "dataset = dataset.batch(50)\n",
    "# 创建验证集Dataset\n",
    "val_dataset = tf.data.Dataset.from_tensor_slices((val_data, val_labels))\n",
    "val_dataset = val_dataset.batch(50)\n",
    "\n",
    "model.fit(dataset, epochs=2, validation_data=val_dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = np.random.random((1000, 32))\n",
    "labels = np.random.random((1000, 10))\n",
    "\n",
    "# 模型评估，测试集为NumPy数据\n",
    "model.evaluate(data, labels, batch_size=50)\n",
    "# 模型评估，测试集为Dataset数据\n",
    "model.evaluate(dataset, steps=30)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = model.predict(data, batch_size=50)\n",
    "print(result[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构建高级模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 单独的一个输入层\n",
    "inputs = tf.keras.Input(shape=(32,))\n",
    "# 网络层可以像函数一样被调用，其接收和输出的均为张量\n",
    "x = layers.Dense(64, activation='relu')(inputs)\n",
    "x = layers.Dense(64, activation='relu')(x)\n",
    "# 输出层\n",
    "predictions = layers.Dense(10, activation='softmax')(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建模型\n",
    "model = tf.keras.Model(inputs=inputs, outputs=predictions)\n",
    "# 编译模型\n",
    "model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])\n",
    "# 训练模型\n",
    "model.fit(data, labels, epochs=2, batch_size=50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 自定义网络模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MyModel(tf.keras.Model):\n",
    "\n",
    "  def __init__(self, num_classes=10):\n",
    "    super(MyModel, self).__init__(name='my_model')\n",
    "    # 分类任务的类别数\n",
    "    self.num_classes = num_classes\n",
    "    # 定义我们自己的网络层\n",
    "    self.dense_1 = layers.Dense(32, activation='relu')\n",
    "    self.dense_2 = layers.Dense(num_classes, activation='sigmoid')\n",
    "\n",
    "  def call(self, inputs):\n",
    "    # 使用“__init__”方法中定义的网络层来构造网络的前馈过程\n",
    "    x = self.dense_1(inputs)\n",
    "    return self.dense_2(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = MyModel(num_classes=10)\n",
    "# 编译模型\n",
    "model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])\n",
    "# 训练模型\n",
    "model.fit(data, labels, batch_size=50, epochs=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "callbacks = [\n",
    "  # 当验证集上的损失“val_loss”连续两个训练回合（epoch）都没有变化，则提前结束训练\n",
    "  tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),\n",
    "  # 使用TensorBoard保存训练的记录，保存到“./logs”目录中\n",
    "  tf.keras.callbacks.TensorBoard(log_dir='./logs')\n",
    "]\n",
    "model.fit(data, labels, batch_size=50, epochs=5, callbacks=callbacks,\n",
    "          validation_data=(val_data, val_labels))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个简单的模型\n",
    "model = tf.keras.Sequential([\n",
    "  layers.Dense(10, activation='softmax', input_shape=(32,)),\n",
    "  layers.Dense(10, activation='softmax')\n",
    "])\n",
    "model.compile(optimizer='rmsprop',\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])\n",
    "model.fit(data, labels, batch_size=32, epochs=5)\n",
    "\n",
    "# 将整个模型保存为HDF5文件\n",
    "model.save('my_model')\n",
    "# 加载保存的模型\n",
    "model = tf.keras.models.load_model('my_model')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将模型的权重参数保存为HDF5文件\n",
    "model.save_weights('my_model.h5', save_format='h5')\n",
    "# 重新加载\n",
    "model.load_weights('my_model.h5')\n",
    "\n",
    "# 将模型的结构保存为JSON文件\n",
    "json_string = model.to_json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "source": [],
    "metadata": {
     "collapsed": false
    }
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}